home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / share / festival / singing-mode.scm < prev    next >
Encoding:
Text File  |  2006-12-20  |  16.1 KB  |  585 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;
  3. ;;; Festival Singing Mode
  4. ;;;
  5. ;;; Written by Dominic Mazzoni
  6. ;;; Carnegie Mellon University
  7. ;;; 11-752 - "Speech: Phonetics, Prosody, Perception and Synthesis"
  8. ;;; Spring 2001
  9. ;;;
  10. ;;; This code is public domain; anyone may use it freely.
  11. ;;;
  12. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  13.  
  14. (require_module 'rxp)
  15.  
  16. (xml_register_id "-//SINGING//DTD SINGING mark up//EN"
  17.         (path-append xml_dtd_dir "Singing.v0_1.dtd")
  18.         )
  19.  
  20. (xml_register_id "-//SINGING//ENTITIES Added Latin 1 for SINGING//EN"
  21.          (path-append xml_dtd_dir  "sable-latin.ent")
  22.          )
  23.  
  24. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  25. ;;
  26. ;; XML parsing functions
  27. ;;
  28. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  29.  
  30. ;;
  31. ;; singing_xml_targets
  32. ;;
  33. ;; This variable defines the actions that are to be taken when
  34. ;; parsing each of our XML tags: SINGING, PITCH, DURATION, and REST.
  35. ;;
  36. ;; When we get the pitch and duration of each token, we store them
  37. ;; in features of the token.  Later our intonation and duration
  38. ;; functions access these features.
  39. ;;
  40.  
  41. (defvar singing_xml_elements
  42. '(
  43.   ("(SINGING" (ATTLIST UTT)
  44.    (set! singing_pitch_att_list nil)
  45.    (set! singing_dur_att_list nil)
  46.    (set! singing_global_time 0.0)
  47.    (set! singing_bpm (get-bpm ATTLIST))
  48.    (set! singing_bps (/ singing_bpm 60.0))
  49.    nil
  50.   )
  51.  
  52.   (")SINGING" (ATTLIST UTT)
  53.     (xxml_synth UTT)  ;;  Synthesize the remaining tokens
  54.     nil
  55.   )
  56.  
  57.   ("(PITCH" (ATTLIST UTT)
  58.    (set! singing_pitch_att_list ATTLIST)
  59.    UTT)
  60.  
  61.   (")PITCH" (ATTLIST UTT)
  62.    (let ((freq (get-freqs singing_pitch_att_list)))
  63.      (print "freqs")
  64.      (print freq)
  65.      (maptail (lambda (item) (item.set_feat item 'freq freq))
  66.               (utt.relation.items UTT 'Token)))
  67.    UTT)
  68.  
  69.   ("(DURATION" (ATTLIST UTT)
  70.    (set! singing_dur_att_list ATTLIST)
  71.    UTT)
  72.  
  73.   (")DURATION" (ATTLIST UTT)
  74.    (let ((dur (get-durs singing_dur_att_list)))
  75.      (print "durs")
  76.      (print dur)
  77.      (maptail (lambda (item) (item.set_feat item 'dur dur))
  78.               (utt.relation.items UTT 'Token)))
  79.    UTT)
  80.  
  81.   ("(REST" (ATTLIST UTT)
  82.    (let ((dur (get-durs ATTLIST)))
  83.      (print "rest durs")
  84.      (print dur)
  85.      (maptail (lambda (item) (item.set_feat item 'rest (car dur)))
  86.               (utt.relation.items UTT 'Token)))
  87.    UTT)
  88. ))
  89.  
  90. ;;
  91. ;; get-bpm
  92. ;;
  93. ;; Given the attribute list of a SINGING tag, returns the beats
  94. ;; per minute of the song from the BPM parameter.
  95. ;;
  96.  
  97. (define (get-bpm atts)
  98.   (parse-number (car (car (cdr (assoc 'BPM atts))))))
  99.  
  100. ;;
  101. ;; get-durs
  102. ;;
  103. ;; Given the attribute list of a DURATION tag, returns a list of
  104. ;; durations in seconds for the syllables of the word enclosed by
  105. ;; this tag.
  106. ;;
  107. ;; It first looks for a BEATS parameter, and converts these to
  108. ;; seconds using BPM, which was set in the SINGING tag.  If this
  109. ;; is not present, it looks for the SECONDS parameter.
  110. ;;
  111.  
  112. (define (get-durs atts)
  113.   (set! seconds (car (car (cdr (assoc 'SECONDS atts)))))
  114.   (set! beats (car (car (cdr (assoc 'BEATS atts)))))
  115.   (if (equal? beats 'X)
  116.       (mapcar (lambda (x) (parse-number x))
  117.               (string2list seconds))
  118.       (mapcar (lambda (x) (/ (parse-number x) singing_bps))
  119.               (string2list beats))))
  120.  
  121. ;;
  122. ;; get-freqs
  123. ;;
  124. ;; Given the attribute list of a PITCH tag, returns a list of
  125. ;; frequencies in Hertz for the syllables of the word enclosed by
  126. ;; this tag.
  127. ;;
  128. ;; It first looks for a NOTE parameter, which can contain a MIDI
  129. ;; note of the form "C4", "D#3", or "Ab6", and if this is not
  130. ;; present it looks for the FREQ parameter.
  131. ;;
  132.  
  133. (define (get-freqs atts)
  134.   (set! freqs (car (car (cdr (assoc 'FREQ atts)))))
  135.   (set! notes (car (car (cdr (assoc 'NOTE atts)))))
  136.   (if (equal? notes 'X)
  137.       (mapcar (lambda (x) (parse-number x))
  138.               (string2list freqs))
  139.       (mapcar (lambda (x) (note2freq x))
  140.               (string2list notes))))
  141.  
  142. ;;
  143. ;; note2freq
  144. ;;
  145. ;; Converts a string representing a MIDI note such as "C4" and
  146. ;; turns it into a frequency.  We use the convention that
  147. ;; A5=440 (some call this note A3).
  148. ;;
  149.  
  150. (define (note2freq note)
  151.   (format t "note is %l\n" note)
  152.   (set! note (print_string note))
  153.   (set! l (string-length note))
  154.   (set! octave (substring note (- l 2) 1))
  155.   (set! notename (substring note 1 (- l 3)))
  156.   (set! midinote (+ (* 12 (parse-number octave))
  157.                     (notename2midioffset notename)))
  158.   (set! thefreq (midinote2freq midinote))
  159.   (format t "note %s freq %f\n" note thefreq)
  160.   thefreq)
  161.  
  162. ;;
  163. ;; midinote2freq
  164. ;;
  165. ;; Converts a MIDI note number (1 - 127) into a frequency.  We use
  166. ;; the convention that 69 = "A5" =440 Hz.
  167. ;;
  168.  
  169. (define (midinote2freq midinote)
  170.   (* 440.0 (pow 2.0 (/ (- midinote 69) 12))))
  171.  
  172. ;;
  173. ;; notename2midioffset
  174. ;;
  175. ;; Utility function that looks up the name of a note like "F#" and
  176. ;; returns its offset from C.
  177. ;;
  178.  
  179. (define (notename2midioffset notename)
  180.   (set! ans (parse-number (car (cdr (assoc_string notename note_names)))))
  181.   ans
  182. )
  183.  
  184. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  185. ;;
  186. ;; Pitch modification functions
  187. ;;
  188. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  189.  
  190. ;;
  191. ;; singing_f0_targets
  192. ;;
  193. ;; This function replaces the normal intonation function used in
  194. ;; festival.  For each syllable, it extracts the frequency that
  195. ;; was calculated from the XML tags and stored in the token this
  196. ;; syllable comes from, and sets this frequency as both the start
  197. ;; and end f0 target.  Really straightforward!
  198. ;;
  199.  
  200. (define (singing_f0_targets utt syl)
  201.   "(singing_f0_targets utt syl)"
  202.  
  203.   (let ((freq (parse-number (syl2freq syl)))
  204.         (start (item.feat syl 'syllable_start))
  205.         (end (item.feat syl 'syllable_end)))
  206.     (list (list start freq)
  207.           (list end freq))))
  208.  
  209. ;;
  210. ;; syl2freq
  211. ;;
  212. ;; Given a syllable, looks up the frequency in its token.  The token
  213. ;; stores a list of all of the frequencies associated with its
  214. ;; syllables, so this syllable grabs the frequency out of the list
  215. ;; corresponding to its index within the word.  (This assumes that
  216. ;; a frequency was given for each syllable, and that a token
  217. ;; corresponds directly to a word.  Singing-mode is not guaranteed
  218. ;; to work at all if either of these things are not true.)
  219. ;;
  220.  
  221. (define (syl2freq syl)
  222.   (set! index (item.feat syl "R:Syllable.pos_in_word"))
  223.   (set! freqs (item.feat syl "R:SylStructure.parent.R:Token.parent.freq"))
  224.   (my_nth freqs index))
  225.  
  226. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  227. ;;
  228. ;; Duration modification functions
  229. ;;
  230. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  231.  
  232. ;;
  233. ;; singing_duration_method 
  234. ;;
  235. ;; Calculates the duration of each phone in the utterance, in three
  236. ;; passes.  Consult the three functions it calls, below, to see what
  237. ;; each one does.
  238. ;;
  239.  
  240. (define (singing_duration_method utt)
  241.   (mapcar singing_adjcons_syllable (utt.relation.items utt 'Syllable))  
  242.   (mapcar singing_do_syllable (utt.relation.items utt 'Syllable))
  243.   (mapcar singing_fix_segment (utt.relation.items utt 'Segment))
  244.   utt)
  245.  
  246. ;;
  247. ;; singing_adjcons_syllable
  248. ;;
  249. ;; First pass.  Looks at the first phone of each syllable and
  250. ;; adjusts the starting time of this syllable such that the
  251. ;; perceived start time of the first phone is at the beginning
  252. ;; of the originally intended start time of the syllable.
  253. ;;
  254. ;; If this is not done, telling it to say the word "ta" at time
  255. ;; 2.0 actually doesn't "sound" like it says the "t" sound until
  256. ;; about 2.1 seconds.
  257. ;;
  258. ;; This function has a little bit of duplicated code from
  259. ;; singing_do_syllable, below - it could be modularized a little
  260. ;; better.
  261. ;;
  262.  
  263. (define (singing_adjcons_syllable syl)
  264.   (set! conslen 0.0)
  265.   (set! vowlen 0.0)
  266.   (set! numphones 0)
  267.   ;; sum up the length of all of the vowels and consonants in
  268.   ;; this syllable
  269.   (mapcar (lambda (s)
  270.             (set! slen (get_avg_duration (item.feat s "name")))
  271.             (set! numphones (+ 1 numphones))
  272.             (if (equal? "+" (item.feat s "ph_vc"))
  273.                 (set! vowlen (+ vowlen slen))
  274.                 (set! conslen (+ conslen slen))))
  275.           (item.leafs (item.relation syl 'SylStructure)))
  276.   (set! totlen (+ conslen vowlen))
  277.   (set! syldur (syl2dur syl))
  278.   ;; figure out the offset of the first phone
  279.   (set! phone1 (item.daughter1 (item.relation syl 'SylStructure)))
  280.   (set! offset (get_duration_offset (item.feat phone1 "name")))
  281.   (format t "offset: %f\n" offset) 
  282.  (if (< syldur totlen)
  283.       (set! offset (* offset (/ syldur totlen))))
  284.   (set! prevsyl (item.prev (item.relation syl 'Syllable)))
  285.   (format t "Want to adjust syl by %f\n" offset)
  286.   (if (equal? nil prevsyl)
  287.       nil
  288.       (let ()
  289.         (item.set_feat prevsyl 'subtractoffset offset)
  290.         (item.set_feat syl 'addoffset offset))))
  291.  
  292. ;;
  293. ;; singing_do_syllable
  294. ;;
  295. ;; Second pass.  For each syllable, adds up the amount of time
  296. ;; that would normally be spent in consonants and vowels, based
  297. ;; on the average durations of these phones.  Then, if the
  298. ;; intended length of this syllable is longer than this total,
  299. ;; stretch only the vowels; otherwise shrink all phones
  300. ;; proportionally.  This function actually sets the "end" time
  301. ;; of each phone using a global "singing_global_time" variable.
  302. ;;
  303. ;; We also handle rests at this point, which are tagged onto the
  304. ;; end of the previous token.
  305. ;;
  306.  
  307. (define (singing_do_syllable syl)
  308.   (set! conslen 0.0)
  309.   (set! vowlen 0.0)
  310.   (set! numphones 0)
  311.   ;; sum up the length of all of the vowels and consonants in
  312.   ;; this syllable
  313.   (mapcar (lambda (s)
  314.             (set! slen (get_avg_duration (item.feat s "name")))
  315.             (set! numphones (+ 1 numphones))
  316.             (if (equal? "+" (item.feat s "ph_vc"))
  317.                 (set! vowlen (+ vowlen slen))
  318.                 (set! conslen (+ conslen slen))))
  319.           (item.leafs (item.relation syl 'SylStructure)))
  320.   (set! totlen (+ conslen vowlen))
  321.   (format t "Vowlen: %f conslen: %f totlen: %f\n" vowlen conslen totlen)
  322.   (set! syldur (syl2dur syl))
  323.   (set! addoffset (item.feat syl 'addoffset))
  324.   (set! subtractoffset (item.feat syl 'subtractoffset))
  325.   (set! offset (- subtractoffset addoffset))
  326.   (if (< offset (/ syldur 2.0))
  327.       (let ()
  328.         (set! syldur (- syldur offset))
  329.         (format t "Offset: %f\n" offset)))
  330.   (format t "Syldur: %f\n" syldur)
  331.   (if (> totlen syldur)
  332.       ;; if the total length of the average durations in the syllable is
  333.       ;; greater than the total desired duration of the syllable, stretch
  334.       ;; the time proportionally for each phone
  335.       (let ((stretch (/ syldur totlen)))
  336.         (mapcar (lambda (s)
  337.                   (set! slen (get_avg_duration (item.feat s "name")))
  338.                   (set! slen (* stretch slen))
  339.                   (set! singing_global_time (+ slen singing_global_time))
  340.                   (item.set_feat s 'end singing_global_time))
  341.                 (item.leafs (item.relation syl 'SylStructure))))
  342.  
  343.       ;; otherwise, stretch the vowels and not the consonants
  344.       (let ((voweltime (- syldur conslen)))
  345.         (let ((vowelstretch (/ voweltime vowlen)))
  346.           (mapcar (lambda (s)
  347.                     (set! slen (get_avg_duration (item.feat s "name")))
  348.                     (if (equal? "+" (item.feat s "ph_vc"))
  349.                         (set! slen (* vowelstretch slen)))
  350.                     (set! singing_global_time (+ slen singing_global_time))
  351.                     (item.set_feat s 'end singing_global_time))
  352.                   (item.leafs (item.relation syl 'SylStructure))))))
  353.   (set! restlen (car (syl2rest syl)))
  354.   (format t "restlen %l\n" restlen)
  355.   (if (> restlen 0)
  356.       (let (nil)
  357.         (set! lastseg (item.daughtern (item.relation syl 'SylStructure)))
  358.         (set! SIL (car (car (cdr (assoc 'silences (PhoneSet.description))))))
  359.         (set! singing_global_time (+ restlen singing_global_time))
  360.         (set! pau_item_desc (list SIL
  361.                                   (list
  362.                                    (list "end" singing_global_time))))
  363.         (item.insert (item.relation lastseg 'Segment) pau_item_desc 'after))))
  364.  
  365. ;;
  366. ;; singing_fix_segment
  367. ;;
  368. ;; Third pass.  Finds any segments (phones) that we didn't catch earlier
  369. ;; (say if they didn't belong to a syllable, like silence) and sets them
  370. ;; to zero duration
  371. ;;
  372.  
  373. (define (singing_fix_segment seg)
  374.   (if (equal? 0.0 (item.feat seg 'end))
  375.       (if (equal? nil (item.prev seg))
  376.           (item.set_feat seg 'end 0.0)
  377.           (item.set_feat seg 'end (item.feat (item.prev seg) 'end)))
  378.       (format t "segment: %s end: %f\n" (item.name seg) (item.feat seg 'end))))
  379.   
  380. ;; returns the duration of a syllable (stored in its token)
  381. (define (syl2dur syl)
  382.   (set! index (item.feat syl "R:Syllable.pos_in_word"))
  383.   (set! durs (item.feat syl "R:SylStructure.parent.R:Token.parent.dur"))
  384.   (my_nth durs index))
  385.  
  386. ;; returns the duration of the rest following a syllable
  387. (define (syl2rest syl)
  388.   (set! index (item.feat syl "R:Syllable.pos_in_word"))
  389.   (set! durs (item.feat syl "R:SylStructure.parent.R:Token.parent.dur"))
  390.   (set! numsyllables (length durs))
  391.   (set! pauselen (item.feat syl "R:SylStructure.parent.R:Token.parent.rest"))
  392.   (if (equal? index (- numsyllables 1))
  393.       (if (equal? pauselen nil)
  394.           (list 0.0)
  395.           (list pauselen))
  396.       (list 0.0)))
  397.  
  398. ;; get the average duration of a phone
  399. (define (get_avg_duration phone)
  400.   (let ((pd (assoc_string phone phoneme_durations)))
  401.     (if pd
  402.     (car (cdr pd))
  403.     0.08)))
  404.  
  405. ;; get the duration offset of a phone (see the description above)
  406. (define (get_duration_offset phone)
  407.   (parse-number (car (cdr (assoc_string phone phoneme_offsets)))))
  408.  
  409. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  410. ;;
  411. ;; Other utility functions
  412. ;;
  413. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  414.  
  415. ;; turns the string "0.5,1.0,2.5" into the list (0.5 1.0 2.5)
  416. (define (string2list str)
  417.   (if (string-matches str ".+,.+")
  418.       (cons (string-before str ",") (string2list (string-after str ",")))
  419.       (list (string-append str ""))))
  420.  
  421. ;; applies fn to the last element in l"
  422. (define (maptail fn l)
  423.   (if (equal? l nil)
  424.       nil
  425.       (if (equal? (cdr l) nil)
  426.           (list (fn (car l)))
  427.           (cons (car l) (maptail fn (cdr l))))))
  428.  
  429.  
  430. ;; returns the nth element of list l, 0-based
  431. (define (my_nth l n)
  432.   (if (equal? n 0)
  433.       (car l)
  434.       (my_nth (cdr l) (- n 1))))
  435.  
  436. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  437. ;;
  438. ;; Initializing and exiting singing mode
  439. ;;
  440. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  441.  
  442. ;;
  443. ;; singing_init_func
  444. ;;
  445.  
  446. (define (singing_init_func)
  447.   "(singing_init_func) - Initialization for Singing mode"
  448.  
  449.   ;; use mwm's voice, it's very nice (or tll for female)
  450.   (set! phoneme_durations  duration_ph_info)
  451.  
  452.   ;; need to use OGI's phoneme_durations since that's what mwm uses
  453. ;  (load (library_expand_filename "ogi_gswdurtreeZ_wb.scm"))
  454.  
  455.   ;; use our intonation function
  456.   (Parameter.set 'Int_Method 'General)
  457.   (Parameter.set 'Int_Target_Method Int_Targets_General)
  458.   (set! int_general_params
  459.         (list 
  460.          (list 'targ_func singing_f0_targets)))
  461.  
  462.   ;; use our duration function
  463.   (Parameter.set 'Duration_Method singing_duration_method)
  464.  
  465.   ;; use our xml parsing function
  466.   (set! singing_previous_elements xxml_elements)
  467.   (set! xxml_elements singing_xml_elements))
  468.  
  469. ;;
  470. ;; singing_exit_func
  471. ;;
  472.  
  473. (define (singing_exit_func)
  474.   "(singing_exit_func) - Exit function for Singing mode"
  475.   (set! xxml_elements singing_previous_elements))
  476.  
  477. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  478. ;;
  479. ;; Data tables
  480. ;;
  481. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  482.  
  483. (set! note_names
  484.       '((C 0)
  485.         (C# 1)
  486.         (Db 1)
  487.         (D 2)
  488.         (D# 3)
  489.         (Eb 3)
  490.         (E 4)
  491.         (E# 5)
  492.         (Fb 4)
  493.         (F 5)
  494.         (F# 6)
  495.         (Gb 6)
  496.         (G 7)
  497.         (G# 8)
  498.         (Ab 8)
  499.         (A 9)
  500.         (A# 10)
  501.         (Bb 10)
  502.         (B 11)
  503.         (B# 12)
  504.         (Cb 11)))
  505.  
  506.  
  507. ;;
  508. ;; The following list contains the offset into each phone that best
  509. ;; represents the perceptual onset of the phone.  This is important
  510. ;; to know to get durations right in singing.  For example, if the
  511. ;; offset for "t" is .060, and you want to start a "t" sound at
  512. ;; time 2.0 seconds, you should actually start the phone playing
  513. ;; at time 1.940 seconds in order for it to sound like the onset of
  514. ;; the "t" is really right at 2.0.
  515. ;;
  516. ;; These were derived empically by looking at and listening to the
  517. ;; waveforms of each phone for mwm's voice.
  518. ;;
  519. (set! phoneme_offsets
  520. '(
  521. (t 0.050)
  522. (T 0.050)
  523. (d 0.090)
  524. (D 0.090)
  525. (p 0.080)
  526. (b 0.080)
  527. (k 0.090)
  528. (g 0.100)
  529. (9r 0.050) ;; r
  530. (l 0.030)
  531. (f 0.050)
  532. (v 0.050)
  533. (s 0.040)
  534. (S 0.040)
  535. (z 0.040)
  536. (Z 0.040)
  537. (n 0.040)
  538. (N 0.040)
  539. (m 0.040)
  540. (j 0.090)
  541. (E 0.0)
  542. (> 0.0)
  543. (>i 0.0)
  544. (aI 0.0)
  545. (& 0.0)
  546. (3r 0.0)
  547. (tS 0.0)
  548. (oU 0.0)
  549. (aU 0.0)
  550. (A 0.0)
  551. (ei 0.0)
  552. (iU 0.0)
  553. (U 0.0)
  554. (@ 0.0)
  555. (h 0.0)
  556. (u 0.0)
  557. (^ 0.0)
  558. (I 0.0)
  559. (dZ 0.0)
  560. (i: 0.0)
  561. (w 0.0)
  562. (pau 0.0)
  563. (brth 0.0)
  564. (h# 0.0)
  565. ))
  566.  
  567.  
  568. ;;
  569. ;; Declare the new mode to Festival
  570. ;;
  571.  
  572. (set! tts_text_modes
  573.    (cons
  574.     (list
  575.       'singing   ;; mode name
  576.       (list         
  577.        (list 'init_func singing_init_func)
  578.        (list 'exit_func singing_exit_func)
  579.        '(analysis_type xml)
  580.        ))
  581.     tts_text_modes))
  582.  
  583. (provide 'singing-mode)
  584.  
  585.